/*
 * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.spi.extension;

import org.omg.CORBA.Policy;
import org.omg.CORBA.LocalObject;
import com.sun.corba.se.impl.orbutil.ORBConstants;

/**
 * Policy used to implement servant caching optimization in the POA.
 * Creating a POA with an instance pol of this policy where
 * pol.getType() &gt; NO_SERVANT_CACHING will cause the servant to be
 * looked up in the POA and cached in the LocalClientRequestDispatcher when
 * the ClientRequestDispatcher is colocated with the implementation of the
 * objref.  This greatly speeds up invocations at the cost of violating the
 * POA semantics.  In particular, every request to a particular objref
 * must be handled by the same servant.  Note that this is typically the
 * case for EJB implementations.
 * <p>
 * If servant caching is used, there are two different additional
 * features of the POA that are expensive:
 * <ol>
 * <li>POA current semantics
 * <li>Proper handling of POA destroy.
 * <ol>
 * POA current semantics requires maintaining a ThreadLocal stack of
 * invocation information that is always available for POACurrent operations.
 * Maintaining this stack is expensive on the timescale of optimized co-located
 * calls, so the option is provided to turn it off.  Similarly, causing
 * POA.destroy() calls to wait for all active calls in the POA to complete
 * requires careful tracking of the entry and exit of invocations in the POA.
 * Again, tracking this is somewhat expensive.
 */
public class ServantCachingPolicy extends LocalObject implements Policy {
    /**
     * Do not cache servants in the ClientRequestDispatcher.  This will
     * always support the full POA semantics, including changing the
     * servant that handles requests on a particular objref.
     */
    public static final int NO_SERVANT_CACHING = 0;

    /**
     * Perform servant caching, preserving POA current and POA destroy semantics.
     * We will use this as the new default, as the app server is making heavier use
     * now of POA facilities.
     */
    public static final int FULL_SEMANTICS = 1;

    /**
     * Perform servant caching, preservent only POA current semantics.
     * At least this level is required in order to support selection of ObjectCopiers
     * for co-located RMI-IIOP calls, as the current copier is stored in
     * OAInvocationInfo, which must be present on the stack inside the call.
     */
    public static final int INFO_ONLY_SEMANTICS = 2;

    /**
     * Perform servant caching, not preserving POA current or POA destroy semantics.
     */
    public static final int MINIMAL_SEMANTICS = 3;

    private static ServantCachingPolicy policy = null;
    private static ServantCachingPolicy infoOnlyPolicy = null;
    private static ServantCachingPolicy minimalPolicy = null;

    private int type;

    public String typeToName() {
        switch (type) {
            case FULL_SEMANTICS:
                return "FULL";
            case INFO_ONLY_SEMANTICS:
                return "INFO_ONLY";
            case MINIMAL_SEMANTICS:
                return "MINIMAL";
            default:
                return "UNKNOWN(" + type + ")";
        }
    }

    public String toString() {
        return "ServantCachingPolicy[" + typeToName() + "]";
    }

    private ServantCachingPolicy(int type) {
        this.type = type;
    }

    public int getType() {
        return type;
    }

    /**
     * Return the default servant caching policy.
     */
    public synchronized static ServantCachingPolicy getPolicy() {
        return getFullPolicy();
    }

    public synchronized static ServantCachingPolicy getFullPolicy() {
        if (policy == null)
            policy = new ServantCachingPolicy(FULL_SEMANTICS);

        return policy;
    }

    public synchronized static ServantCachingPolicy getInfoOnlyPolicy() {
        if (infoOnlyPolicy == null)
            infoOnlyPolicy = new ServantCachingPolicy(INFO_ONLY_SEMANTICS);

        return infoOnlyPolicy;
    }

    public synchronized static ServantCachingPolicy getMinimalPolicy() {
        if (minimalPolicy == null)
            minimalPolicy = new ServantCachingPolicy(MINIMAL_SEMANTICS);

        return minimalPolicy;
    }

    public int policy_type() {
        return ORBConstants.SERVANT_CACHING_POLICY;
    }

    public org.omg.CORBA.Policy copy() {
        return this;
    }

    public void destroy() {
        // NO-OP
    }
}
